package crypto

import (
	"crypto/md5"
	"encoding/base64"
	"encoding/hex"
	"errors"
	"github.com/wenzhenxi/gorsa"
	"higame/modules/log"
	"higame/modules/utils"
	"strings"
)

// 生成32位MD5
func Md5encrypt(text string) string {
	ctx := md5.New()
	ctx.Write([]byte(text))
	md5Str := hex.EncodeToString(ctx.Sum(nil))
	return strings.ToUpper(md5Str)
}

// rc4解密
func RC4Decrypt(text string, pwd string) (string, error) {
	encrypted, err := base64.StdEncoding.DecodeString(text)
	if err != nil {
		return "", err
	}
	if len(text) == 0 || len(pwd) == 0 {
		return "", errors.New("内容或者密匙不能为空！")
	}
	defer func() {
		if err := recover(); err != nil {
			log.Error.Printf("RC4Decrypt:%v\n", err)
		}
	}()
	text = string(encrypted)
	text_rune := []rune(text)
	pwd_rune := []rune(pwd)
	var key = make([]rune, 256)
	var box = make([]rune, 256)
	for i := 0; i < 256; i++ {
		key[i] = pwd_rune[i%len(pwd_rune)]
		box[i] = rune(i)
	}

	j := 0
	for i := 0; i < 256; i++ {
		j = (j + int(box[i]) + int(key[i])) % 256
		box[i], box[j] = box[j], box[i]
	}
	cipher := ""
	a := 0
	j = 0
	for i := 0; i < len(text_rune); i++ {
		a = (a + 1) % 256
		j = (j + int(box[a])) % 256
		var k int
		box[a], box[j] = box[j], box[a]
		k = int(box[(int(box[a])+int(box[j]))%256])
		charNum := int(text_rune[i]) ^ k
		cipher += string(charNum)
	}
	return cipher, nil
}

// rc4加密
func RC4Encrypt(text string, pwd string) (string, error) {
	defer func() {
		if err := recover(); err != nil {
			log.Error.Printf("RC4Decrypt:%v\n", err)
		}
	}()
	if len(text) == 0 || len(pwd) == 0 {
		return "", errors.New("内容或者密匙不能为空！")
	}
	text_rune := []rune(text)
	pwd_rune := []rune(pwd)
	var key = make([]rune, 256)
	var box = make([]rune, 256)
	for i := 0; i < 256; i++ {
		key[i] = pwd_rune[i%len(pwd_rune)]
		box[i] = rune(i)
	}

	j := 0
	for i := 0; i < 256; i++ {
		j = (j + int(box[i]) + int(key[i])) % 256
		box[i], box[j] = box[j], box[i]
	}
	cipher := ""
	a := 0
	j = 0
	for i := 0; i < len(text_rune); i++ {
		a = (a + 1) % 256
		j = (j + int(box[a])) % 256
		var k int
		box[a], box[j] = box[j], box[a]
		k = int(box[(int(box[a])+int(box[j]))%256])
		charNum := int(text_rune[i]) ^ k
		cipher += string(charNum)
	}

	return base64.StdEncoding.EncodeToString([]byte(cipher)), nil
}

// 自定义解密
func MyDecrypt(plainText string, enRc4Key string, rsaPrivateKey string) (json map[string]interface{}, rc4Key string) {

	rc4Key, err := gorsa.PriKeyDecrypt(enRc4Key, rsaPrivateKey)
	if err != nil {
		log.Error.Printf("MyDecrypt:%v\n", err)
		return nil, ""
	}
	jsonStr, err := RC4Decrypt(plainText, rc4Key)
	if err != nil {
		log.Error.Printf("MyDecrypt:%v\n", err)
		return nil, ""
	}
	utils.ParseJson(jsonStr, &json)
	return
}

// 自定义加密
func MyEncrypt(plainText string, privateKey string) (enRc4Key string, enRc4Data string) {
	rc4Key := utils.MakeKey(10)
	enRc4Key, err := gorsa.PriKeyEncrypt(rc4Key, privateKey)
	if err != nil {
		log.Error.Printf("MyEncrypt:%v\n", err)
		return
	}
	enRc4Data, err = RC4Encrypt(plainText, rc4Key)
	if err != nil {
		log.Error.Printf("MyDecrypt:%v\n", err)
		return
	}
	return
}
